package com.xhb.biz.service;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.solon.service.impl.ServiceImpl;
import com.teamdev.jxbrowser.cookie.Cookie;
import com.teamdev.jxbrowser.cookie.CookieStore;
import com.teamdev.jxbrowser.view.swing.BrowserView;
import com.xhb.biz.constant.UserConfigConstant;
import com.xhb.biz.feign.FeignUtils;
import com.xhb.biz.feign.UserTokenService;
import com.xhb.biz.mapper.ConfigMapper;
import com.xhb.biz.po.ConfigPO;
import feign.Feign;
import feign.Request;
import feign.Retryer;
import feign.jackson.JacksonEncoder;
import org.noear.solon.annotation.Inject;
import org.noear.solon.aspect.annotation.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;

/**
 * (Config)}表服务接口
 *
 * @author tanyukun
 * @since 2023-02-07 11:35:02
 */
@Service
public class ConfigService extends ServiceImpl<ConfigMapper, ConfigPO> {

    @Inject("${manager.url}")
    public String managerServerUrl;
    @Inject("${easy-borwser.default-index}")
    public String userIndexUrl;

    public String getManagerServerIp() {
        return managerServerUrl.replace("http://", "").replace("https://", "").split(":")[0];
    }

    public Map<String, Object> getHeaders() {
        ConfigPO configPo = selectUserConfigByKey(UserConfigConstant.USER_TOKEN_KEY);
        return Collections.singletonMap(UserConfigConstant.USER_TOKEN_KEY, configPo.getContent());
    }

    UserTokenService userTokenService;

    public UserTokenService getUserTokenService() {
        if (null == userTokenService) {
            userTokenService = Feign.builder()
                    .encoder(new JacksonEncoder())
                    .options(new Request.Options(1000, 3500))
                    .retryer(new Retryer.Default(5000, 5000, 3))
                    .target(UserTokenService.class, managerServerUrl);
        }
        return userTokenService;
    }

    public JSONObject login(String userName, String password) {
        JSONObject paramMap = new JSONObject(2);
        paramMap.set("userLoginName", userName);
        paramMap.set("password", SecureUtil.md5(password));
        String login = null;
        try {
            login = getUserTokenService().login(paramMap.toString());
        } catch (Exception e) {
            return new JSONObject().set("code", 400).set("message", FeignUtils.getFeignErrorMessage(e));
        }
        return JSONUtil.parseObj(login);
    }

    public JSONObject logout(BrowserView localBrowserView) {
        String result;
        try {
            result = getUserTokenService().logout(getHeaders());
        } catch (Exception e) {
            return new JSONObject().set("code", 400).set("message", FeignUtils.getFeignErrorMessage(e));
        }
        CookieStore cookieStore = localBrowserView.getBrowser().profile().cookieStore();
        List<Cookie> cookies = cookieStore.cookies();
        cookies.forEach(cookie -> {
            if (cookie.domain().contains(getManagerServerIp())) {
                cookieStore.delete(cookie);
            }
        });
        return JSONUtil.parseObj(result);
    }

    /**
     * 判断登陆状态
     *
     * @return
     */
    public JSONObject checkTokenStatus() {
        AtomicReference<JSONObject> result = new AtomicReference<>();
        CompletableFuture.runAsync(() -> {
            String resultStr;
            try {
                if (null == getHeaders()) {
                    result.set(new JSONObject());
                } else {
                    resultStr = getUserTokenService().checkTokenStatus(getHeaders());
                    result.set(JSONUtil.parseObj(resultStr));
                }
            } catch (Exception e) {
                result.set(new JSONObject().set("code", 400).set("message", FeignUtils.getFeignErrorMessage(e)));
            }
        });
        return result.get();
    }

    /**
     * 保存登录 token 到数据库
     *
     * @param dataObj 登录返回的用户信息
     */
    public void saveLoginToken(JSONObject dataObj) {
        ConfigMapper configMapper = super.getBaseMapper();
        LambdaQueryWrapper<ConfigPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ConfigPO::getKey, UserConfigConstant.USER_TOKEN_KEY);
        ConfigPO configPo = configMapper.selectOne(wrapper);
        String token = dataObj.getStr("token");
        if (null == configPo) {
            configPo = ConfigPO.builder()
                    .key(UserConfigConstant.USER_TOKEN_KEY)
                    .content(token)
                    .build();
            configMapper.insert(configPo);
        } else {
            configPo.setContent(token);
            configMapper.updateById(configPo);
        }
    }

    /**
     * 根据 key 获取单个用户配置
     *
     * @return
     */
    public ConfigPO selectUserConfigByKey(String key) {
        ConfigMapper configMapper = super.getBaseMapper();
        LambdaQueryWrapper<ConfigPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ConfigPO::getKey, key);
        return configMapper.selectOne(wrapper);
    }

    /**
     * 根据 key 删除用户配置
     *
     * @return
     */
    public int delUserConfigByKey(String key) {
        ConfigMapper configMapper = super.getBaseMapper();
        LambdaQueryWrapper<ConfigPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ConfigPO::getKey, key);
        return configMapper.delete(wrapper);
    }

    /**
     * 获取用户首页导航
     *
     * @return
     */
    public String getUserIndexUrl(String url) {
        if (url == null) {
            url = userIndexUrl;
        } else if (!url.contains(userIndexUrl)) {
            return url;
        }
        ConfigPO configPo = selectUserConfigByKey(UserConfigConstant.USER_TOKEN_KEY);
        return url + (null == configPo ? "" : "?token=" + configPo.getContent());
    }

    public Cookie getCookie() {
        ConfigPO configPo = selectUserConfigByKey(UserConfigConstant.USER_TOKEN_KEY);
        if (null == configPo) {
            return null;
        }
        return Cookie.newBuilder(getManagerServerIp())
                .name(UserConfigConstant.USER_TOKEN_KEY)
                .value(configPo.getContent())
                .path("/").build();
    }
}
